package top.lixunda.ecommerce.server.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import top.lixunda.common.utils.ObjectValidators;
import top.lixunda.ecommerce.server.auth.api.entity.dto.EmailNormalDTO;
import top.lixunda.ecommerce.server.auth.api.feign.IFeignEmailAuthCode;
import top.lixunda.ecommerce.server.business.BaseServiceImpl;
import top.lixunda.ecommerce.server.business.api.entity.BusinessConstants;
import top.lixunda.ecommerce.server.business.api.entity.cache.CacheLoginUser;
import top.lixunda.ecommerce.server.business.api.entity.dto.PageDTO;
import top.lixunda.ecommerce.server.user.api.entity.db.*;
import top.lixunda.ecommerce.server.user.api.entity.dto.*;
import top.lixunda.ecommerce.server.user.api.entity.vo.BusinessTaskItemVO;
import top.lixunda.ecommerce.server.user.api.entity.vo.BusinessTaskVO;
import top.lixunda.ecommerce.server.user.mapper.BusinessTaskMapper;
import top.lixunda.ecommerce.server.user.service.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 代办任务数据，保存代办任务 服务实现类
 * </p>
 *
 * @author Xumda
 * @since 2020-04-13
 */
@Slf4j
@Service
public class BusinessTaskServiceImpl
        extends BaseServiceImpl<BusinessTaskMapper, BusinessTaskDO>
        implements IBusinessTaskService {

    private final IBusinessTaskItemService itemService;

    private final IAccountService accountService;

    private final IMessageService messageService;

    private final IUserInfoService userInfoService;

    private final IFeignEmailAuthCode feignEmailAuthCode;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    public BusinessTaskServiceImpl(IBusinessTaskItemService itemService,
                                   IAccountService accountService,
                                   IMessageService messageService,
                                   IUserInfoService userInfoService,
                                   IFeignEmailAuthCode feignEmailAuthCode) {
        this.itemService = itemService;
        this.accountService = accountService;
        this.messageService = messageService;
        this.userInfoService = userInfoService;
        this.feignEmailAuthCode = feignEmailAuthCode;
    }

    /**
     * 将BusinessTaskItemDO列表转换为taskId为键，BusinessTaskItemVO列表位置的Map
     *
     * @param list BusinessTaskItemDO列表
     * @return taskId为键，BusinessTaskItemVO列表位置的Map
     */
    private Map<Integer, List<BusinessTaskItemVO>> convertItemToListMap(List<BusinessTaskItemDO> list) {
        return list.stream()
                .map(BusinessTaskItemVO::fromBusinessTaskItemDO)
                .filter(Objects::nonNull)
                .filter(item -> ObjectValidators.isNotEmpty(item.getTaskId()))
                .collect(Collectors.toMap(BusinessTaskItemVO::getTaskId, item -> {
                    List<BusinessTaskItemVO> tempList = new ArrayList<>();
                    tempList.add(item);
                    return tempList;
                }, (item1, item2) -> {
                    item1.addAll(item2);
                    return item1;
                }));
    }

    /**
     * 通过taskId查询代办任务信息
     *
     * @param taskId 任务编号
     * @return 代办任务信息，包括所有的任务分配数据
     */
    @Override
    public BusinessTaskVO queryTaskByTaskId(Integer taskId) {
        if (ObjectValidators.isEmpty(taskId)) {
            throw getAppException("查询任务信息失败，任务编号不能为空");
        }
        // 查询任务数据
        BusinessTaskDO businessTaskDO = this.getById(taskId);
        if (ObjectValidators.isEmpty(businessTaskDO)) {
            throw getAppException("任务不存在");
        }
        BusinessTaskVO businessTaskVO = BusinessTaskVO.fromBusinessTaskDO(businessTaskDO);
        if (ObjectValidators.isEmpty(businessTaskVO)) {
            businessTaskVO = new BusinessTaskVO();
        }
        // 查询任务子项数据
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(new LambdaQueryWrapper<BusinessTaskItemDO>()
                .eq(BusinessTaskItemDO::getTaskId, taskId));
        if (ObjectValidators.isEmpty(businessTaskItemList)) {
            businessTaskVO.setBusinessTaskItemList(Collections.emptyList());
        } else {
            businessTaskVO.setBusinessTaskItemList(BusinessTaskItemVO.fromBusinessTaskItemDO(businessTaskItemList));
        }
        return businessTaskVO;
    }

    /**
     * 通过taskIds查询代办任务信息
     *
     * @param taskIds 任务编号
     * @return 代办任务信息，包括所有的任务分配数据
     */
    @Override
    public List<BusinessTaskVO> queryTaskByTaskIds(List<Integer> taskIds) {
        if (ObjectValidators.isEmpty(taskIds)) {
            throw getAppException("查询任务信息失败，任务编号不能为空");
        }
        // 查询任务数据
        Collection<BusinessTaskDO> list = this.listByIds(taskIds);
        if (ObjectValidators.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<BusinessTaskVO> resultList = BusinessTaskVO.fromBusinessTaskDO(list);
        if (ObjectValidators.isEmpty(resultList)) {
            return Collections.emptyList();
        }
        // 查询任务子项数据
        List<Integer> taskIdList = resultList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(
                new LambdaQueryWrapper<BusinessTaskItemDO>()
                        .in(BusinessTaskItemDO::getTaskId, taskIdList));
        // 数据转换
        Map<Integer, List<BusinessTaskItemVO>> tempMap = convertItemToListMap(businessTaskItemList);
        resultList.forEach(item -> {
            List<BusinessTaskItemVO> temp = tempMap.get(item.getTaskId());
            item.setBusinessTaskItemList(ObjectValidators.isEmpty(temp) ?
                    Collections.emptyList() : temp);
        });
        return resultList;
    }

    /**
     * 通过taskName查询当前登陆人员的代办任务信息
     *
     * @param taskName 任务名称
     * @return 代办任务信息，只包括当前登陆人员的任务分配数据
     */
    @Override
    public List<BusinessTaskVO> queryTaskByTaskName(String taskName) {
        if (ObjectValidators.isEmpty(taskName)) {
            throw getAppException("查询任务信息失败，任务名称不能为空");
        }
        // 查询任务数据
        List<BusinessTaskDO> businessTaskList = this.list(new LambdaQueryWrapper<BusinessTaskDO>()
                .eq(BusinessTaskDO::getTaskName, taskName));
        if (ObjectValidators.isEmpty(businessTaskList)) {
            return Collections.emptyList();
        }
        List<BusinessTaskVO> businessTaskVoList = BusinessTaskVO.fromBusinessTaskDO(businessTaskList);
        if (ObjectValidators.isEmpty(businessTaskVoList)) {
            return Collections.emptyList();
        }
        // 查询任务子项数据
        List<Integer> taskIdList = businessTaskList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        // 查询数据
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(new LambdaQueryWrapper<BusinessTaskItemDO>()
                .in(BusinessTaskItemDO::getTaskId, taskIdList));
        // 数据转换
        Map<Integer, List<BusinessTaskItemVO>> tempMap = convertItemToListMap(businessTaskItemList);
        businessTaskVoList.forEach(item -> {
            List<BusinessTaskItemVO> temp = tempMap.get(item.getTaskId());
            item.setBusinessTaskItemList(ObjectValidators.isEmpty(temp) ?
                    Collections.emptyList() : temp);
        });
        return businessTaskVoList;
    }

    /**
     * 通过条件分页查询代办任务信息
     *
     * @param pageDTO 条件分页数据
     * @return 分页的代办任务信息
     */
    @Override
    public IPage<BusinessTaskVO> queryTaskByPageWrapper(
            PageDTO<BusinessTaskDO, BusinessTaskQueryDTO> pageDTO) {
        if (ObjectValidators.isEmpty(pageDTO)) {
            throw getAppException("参数不能为空");
        }
        IPage<BusinessTaskDO> tempPage = this.page(pageDTO.getPage(), pageDTO.getWrapper());
        IPage<BusinessTaskVO> page = new Page<>();
        List<BusinessTaskVO> businessTaskVoList = BusinessTaskVO.fromBusinessTaskDO(tempPage.getRecords());
        BeanUtils.copyProperties(tempPage, page);
        if (ObjectValidators.isEmpty(businessTaskVoList)) {
            page.setRecords(Collections.emptyList());
            return page;
        }
        // 查询任务子项数据
        List<Integer> taskIdList = businessTaskVoList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        // 查询数据
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(new LambdaQueryWrapper<BusinessTaskItemDO>()
                .in(BusinessTaskItemDO::getTaskId, taskIdList));
        // 数据转换
        Map<Integer, List<BusinessTaskItemVO>> tempMap = convertItemToListMap(businessTaskItemList);
        businessTaskVoList.forEach(item -> {
            List<BusinessTaskItemVO> temp = tempMap.get(item.getTaskId());
            item.setBusinessTaskItemList(ObjectValidators.isEmpty(temp) ?
                    Collections.emptyList() : temp);
        });
        page.setRecords(businessTaskVoList);
        return page;
    }

    /**
     * 通过taskId查询当前登陆人员的任务信息，登陆权限
     *
     * @param taskId 任务编号
     * @return 任务信息，只包括当前登陆人员的任务分配数据
     */
    @Override
    public BusinessTaskVO queryCurrentUserTaskByTaskId(Integer taskId) {
        if (ObjectValidators.isEmpty(taskId)) {
            throw getAppException("查询任务信息失败，任务编号不能为空");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        // 查询任务数据
        BusinessTaskDO businessTaskDO = this.getById(taskId);
        if (ObjectValidators.isEmpty(businessTaskDO)) {
            throw getAppException("任务不存在");
        }
        BusinessTaskVO businessTaskVO = BusinessTaskVO.fromBusinessTaskDO(businessTaskDO);
        if (ObjectValidators.isEmpty(businessTaskVO)) {
            businessTaskVO = new BusinessTaskVO();
        }
        // 查询任务子项数据
        BusinessTaskItemDO businessTaskItem = itemService.getOne(new LambdaQueryWrapper<BusinessTaskItemDO>()
                        .eq(BusinessTaskItemDO::getTaskId, taskId)
                        .eq(BusinessTaskItemDO::getTaskUserId, cacheLoginUser.getAccount())
                        .eq(BusinessTaskItemDO::getTaskUserType, cacheLoginUser.getType()),
                false);
        if (ObjectValidators.isEmpty(businessTaskItem)) {
            throw getAppException("代办任务不存在");
        } else {
            businessTaskVO.setBusinessTaskItemList(
                    Collections.singletonList(BusinessTaskItemVO.fromBusinessTaskItemDO(businessTaskItem)));
        }
        return businessTaskVO;
    }

    /**
     * 通过taskName查询当前登陆人员的任务信息，登陆权限
     *
     * @param taskName 任务名称
     * @return 任务信息，只包括当前登陆人员的任务分配数据
     */
    @Override
    public List<BusinessTaskVO> queryCurrentUserByTaskName(String taskName) {
        if (ObjectValidators.isEmpty(taskName)) {
            throw getAppException("查询任务信息失败，任务名称不能为空");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        // 查询任务数据
        List<BusinessTaskDO> businessTaskList = this.list(new LambdaQueryWrapper<BusinessTaskDO>()
                .eq(BusinessTaskDO::getTaskName, taskName));
        if (ObjectValidators.isEmpty(businessTaskList)) {
            return Collections.emptyList();
        }
        List<BusinessTaskVO> businessTaskVoList = BusinessTaskVO.fromBusinessTaskDO(businessTaskList);
        if (ObjectValidators.isEmpty(businessTaskVoList)) {
            return Collections.emptyList();
        }
        // 查询任务子项数据
        List<Integer> taskIdList = businessTaskList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        // 查询数据
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(new LambdaQueryWrapper<BusinessTaskItemDO>()
                .in(BusinessTaskItemDO::getTaskId, taskIdList)
                .eq(BusinessTaskItemDO::getTaskUserId, cacheLoginUser.getAccount())
                .eq(BusinessTaskItemDO::getTaskUserType, cacheLoginUser.getType()));
        // 数据转换
        Map<Integer, List<BusinessTaskItemVO>> tempMap = convertItemToListMap(businessTaskItemList);
        businessTaskVoList.forEach(item -> {
            List<BusinessTaskItemVO> temp = tempMap.get(item.getTaskId());
            item.setBusinessTaskItemList(ObjectValidators.isEmpty(temp) ?
                    Collections.emptyList() : temp);
        });
        businessTaskVoList = businessTaskVoList.stream()
                .filter(item -> ObjectValidators.isNotEmpty(item)
                        && ObjectValidators.isNotEmpty(item.getBusinessTaskItemList()))
                .collect(Collectors.toList());
        return businessTaskVoList;
    }

    /**
     * 通过条件分页查询查询当前登陆人员的任务信息，登陆权限
     *
     * @param pageDTO 条件分页数据
     * @return 分页的任务信息
     */
    @Override
    public IPage<BusinessTaskVO> queryCurrentUserTaskByPageWrapper(
            PageDTO<BusinessTaskDO, BusinessTaskQueryDTO> pageDTO) {
        if (ObjectValidators.isEmpty(pageDTO)) {
            throw getAppException("参数不能为空");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        // 查询任务数据
        IPage<BusinessTaskDO> tempPage = this.page(pageDTO.getPage(), pageDTO.getWrapper());
        IPage<BusinessTaskVO> page = new Page<>();
        List<BusinessTaskVO> businessTaskVoList = BusinessTaskVO.fromBusinessTaskDO(tempPage.getRecords());
        BeanUtils.copyProperties(tempPage, page);
        if (ObjectValidators.isEmpty(businessTaskVoList)) {
            page.setRecords(Collections.emptyList());
            return page;
        }
        // 查询任务子项数据
        List<Integer> taskIdList = businessTaskVoList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        // 查询数据
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(
                new LambdaQueryWrapper<BusinessTaskItemDO>()
                        .in(BusinessTaskItemDO::getTaskId, taskIdList)
                        .eq(BusinessTaskItemDO::getTaskUserId, cacheLoginUser.getAccount())
                        .eq(BusinessTaskItemDO::getTaskUserType, cacheLoginUser.getType()));
        // 数据转换
        Map<Integer, List<BusinessTaskItemVO>> tempMap = convertItemToListMap(businessTaskItemList);
        businessTaskVoList.forEach(item -> {
            List<BusinessTaskItemVO> temp = tempMap.get(item.getTaskId());
            item.setBusinessTaskItemList(ObjectValidators.isEmpty(temp) ?
                    Collections.emptyList() : temp);
        });
        businessTaskVoList = businessTaskVoList.stream()
                .filter(item -> ObjectValidators.isNotEmpty(item)
                        && ObjectValidators.isNotEmpty(item.getBusinessTaskItemList()))
                .collect(Collectors.toList());
        page.setRecords(businessTaskVoList);
        return page;
    }

    /**
     * 根据taskId查询当前登陆人员的代办任务，登陆权限
     *
     * @param taskId 任务编号
     * @return 代办任务数据
     */
    @Override
    public BusinessTaskVO queryUserToDoByTaskId(Integer taskId) {
        if (ObjectValidators.isEmpty(taskId)) {
            throw getAppException("查询任务信息失败，任务编号不能为空");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        // 查询任务数据
        BusinessTaskDO businessTaskDO = this.getOne(
                new LambdaQueryWrapper<BusinessTaskDO>()
                        .eq(BusinessTaskDO::getTaskId, taskId)
                        .eq(BusinessTaskDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE),
                false);
        if (ObjectValidators.isEmpty(businessTaskDO)) {
            throw getAppException("代办任务不存在");
        }
        BusinessTaskVO businessTaskVO = BusinessTaskVO.fromBusinessTaskDO(businessTaskDO);
        if (ObjectValidators.isEmpty(businessTaskVO)) {
            businessTaskVO = new BusinessTaskVO();
        }
        // 查询任务子项数据
        BusinessTaskItemDO businessTaskItem = itemService.getOne(new LambdaQueryWrapper<BusinessTaskItemDO>()
                        .eq(BusinessTaskItemDO::getTaskId, taskId)
                        .eq(BusinessTaskItemDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE)
                        .eq(BusinessTaskItemDO::getTaskUserId, cacheLoginUser.getAccount())
                        .eq(BusinessTaskItemDO::getTaskUserType, cacheLoginUser.getType()),
                false);
        if (ObjectValidators.isEmpty(businessTaskItem)) {
            throw getAppException("代办任务不存在");
        } else {
            businessTaskVO.setBusinessTaskItemList(
                    Collections.singletonList(BusinessTaskItemVO.fromBusinessTaskItemDO(businessTaskItem)));
        }
        return businessTaskVO;
    }

    /**
     * 根据taskName查询当前登陆人员的代办任务，登陆权限
     *
     * @param taskName 任务名称
     * @return 代办任务数据
     */
    @Override
    public List<BusinessTaskVO> queryUserToDoByTaskName(String taskName) {
        if (ObjectValidators.isEmpty(taskName)) {
            throw getAppException("查询任务信息失败，任务名称不能为空");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        // 查询任务数据
        List<BusinessTaskDO> businessTaskList = this.list(new LambdaQueryWrapper<BusinessTaskDO>()
                .eq(BusinessTaskDO::getTaskName, taskName)
                .eq(BusinessTaskDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE));
        if (ObjectValidators.isEmpty(businessTaskList)) {
            return Collections.emptyList();
        }
        List<BusinessTaskVO> businessTaskVoList = BusinessTaskVO.fromBusinessTaskDO(businessTaskList);
        if (ObjectValidators.isEmpty(businessTaskVoList)) {
            return Collections.emptyList();
        }
        // 查询任务子项数据
        List<Integer> taskIdList = businessTaskList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        // 查询数据
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(new LambdaQueryWrapper<BusinessTaskItemDO>()
                .in(BusinessTaskItemDO::getTaskId, taskIdList)
                .eq(BusinessTaskItemDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE)
                .eq(BusinessTaskItemDO::getTaskUserId, cacheLoginUser.getAccount())
                .eq(BusinessTaskItemDO::getTaskUserType, cacheLoginUser.getType()));
        // 数据转换
        Map<Integer, List<BusinessTaskItemVO>> tempMap = convertItemToListMap(businessTaskItemList);
        businessTaskVoList.forEach(item -> {
            List<BusinessTaskItemVO> temp = tempMap.get(item.getTaskId());
            item.setBusinessTaskItemList(ObjectValidators.isEmpty(temp) ?
                    Collections.emptyList() : temp);
        });
        businessTaskVoList = businessTaskVoList.stream()
                .filter(item -> ObjectValidators.isNotEmpty(item)
                        && ObjectValidators.isNotEmpty(item.getBusinessTaskItemList()))
                .collect(Collectors.toList());
        return businessTaskVoList;
    }

    /**
     * 根据条件分页信息查询当前登陆人员的代办任务，登陆权限
     *
     * @param pageDTO 条件分页数据
     * @return 分页的代办任务信息
     */
    @Override
    public IPage<BusinessTaskVO> queryUserToDoByPageWrapper(
            PageDTO<BusinessTaskDO, BusinessTaskQueryDTO> pageDTO) {
        if (ObjectValidators.isEmpty(pageDTO)) {
            throw getAppException("参数不能为空");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        // 查询任务数据
        IPage<BusinessTaskDO> tempPage = this.page(pageDTO.getPage(),
                pageDTO.getWrapper(wrapper ->
                        wrapper.eq(BusinessTaskDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE)));
        IPage<BusinessTaskVO> page = new Page<>();
        List<BusinessTaskVO> businessTaskVoList = BusinessTaskVO.fromBusinessTaskDO(tempPage.getRecords());
        BeanUtils.copyProperties(tempPage, page);
        if (ObjectValidators.isEmpty(businessTaskVoList)) {
            page.setRecords(Collections.emptyList());
            return page;
        }
        // 查询任务子项数据
        List<Integer> taskIdList = businessTaskVoList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        // 查询数据
        List<BusinessTaskItemDO> businessTaskItemList = itemService.list(
                new LambdaQueryWrapper<BusinessTaskItemDO>()
                        .in(BusinessTaskItemDO::getTaskId, taskIdList)
                        .eq(BusinessTaskItemDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE)
                        .eq(BusinessTaskItemDO::getTaskUserId, cacheLoginUser.getAccount())
                        .eq(BusinessTaskItemDO::getTaskUserType, cacheLoginUser.getType()));
        // 数据转换
        Map<Integer, List<BusinessTaskItemVO>> tempMap = convertItemToListMap(businessTaskItemList);
        businessTaskVoList.forEach(item -> {
            List<BusinessTaskItemVO> temp = tempMap.get(item.getTaskId());
            item.setBusinessTaskItemList(ObjectValidators.isEmpty(temp) ?
                    Collections.emptyList() : temp);
        });
        businessTaskVoList = businessTaskVoList.stream()
                .filter(item -> ObjectValidators.isNotEmpty(item)
                        && ObjectValidators.isNotEmpty(item.getBusinessTaskItemList()))
                .collect(Collectors.toList());
        page.setRecords(businessTaskVoList);
        return page;
    }

    /**
     * 根据taskId删除任务，登陆权限
     *
     * @param taskIds 任务编号列表
     * @return 关闭的任务数据
     */
    @Override
    public List<BusinessTaskVO> removeTaskByTaskIds(List<Integer> taskIds) {
        if (ObjectValidators.isEmpty(taskIds)) {
            throw getAppException("删除任务失败！参数不能为空！");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        LocalDateTime localDateTime = LocalDateTime.now();
        // 查询数据用于返回
        List<BusinessTaskVO> list = this.queryTaskByTaskIds(taskIds);

        // 删除任务子项
        itemService.update(new LambdaUpdateWrapper<BusinessTaskItemDO>()
                .in(BusinessTaskItemDO::getTaskId, taskIds)
                .set(BusinessTaskItemDO::getState, BusinessConstants.TASK_STATE_REMOVE));
        itemService.remove(new LambdaUpdateWrapper<BusinessTaskItemDO>()
                .in(BusinessTaskItemDO::getTaskId, taskIds));
        // 删除主任务
        this.update(new LambdaUpdateWrapper<BusinessTaskDO>()
                .in(BusinessTaskDO::getTaskId, taskIds)
                .set(BusinessTaskDO::getUpdateTime, localDateTime)
                .set(BusinessTaskDO::getUpdateUserId, cacheLoginUser.getAccount())
                .set(BusinessTaskDO::getUpdateUserType, cacheLoginUser.getType())
                .set(BusinessTaskDO::getUpdateUserName, cacheLoginUser.getName())
                .set(BusinessTaskDO::getState, BusinessConstants.TASK_STATE_REMOVE));
        this.removeByIds(taskIds);

        return list;
    }

    /**
     * 参数转换，将 BusinessTaskStartDTO 转换为 BusinessTaskDO 用于插入
     *
     * @param startDTO BusinessTaskStartDTO
     * @return BusinessTaskDO
     */
    private BusinessTaskDO toBusinessTaskDO(BusinessTaskStartDTO startDTO) {
        BusinessTaskDO businessTaskDO = new BusinessTaskDO();
        if (ObjectValidators.isEmpty(startDTO)) {
            return businessTaskDO;
        }
        BeanUtils.copyProperties(startDTO, businessTaskDO);
        LocalDateTime localDateTime = LocalDateTime.now();
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        businessTaskDO
                .setCreateTime(localDateTime)
                .setCreateUserName(cacheLoginUser.getName())
                .setCreateUserId(cacheLoginUser.getAccount())
                .setCreateUserType(cacheLoginUser.getType());
        return businessTaskDO;
    }

    /**
     * 处理开启任务催办
     *
     * @param list     任务信息
     * @param itemList 任务子项信息
     */
    private void startTaskUrge(List<BusinessTaskDO> list, List<BusinessTaskItemDO> itemList) {
        // todo 添加任务催办，添加定时任务 待定
    }

    /**
     * 处理开启任务消息推送，站内推送
     *
     * @param list    任务信息
     * @param tempMap 任务子项信息
     */
    private void startTaskPushWeb(List<BusinessTaskDO> list, Map<Integer, List<BusinessTaskItemDO>> tempMap) {
        List<MessageInsertDTO> messageList = new ArrayList<>(list.size() * 4);
        list.forEach(item -> {
            List<BusinessTaskItemDO> itemList = tempMap.get(item.getTaskId());
            if (ObjectValidators.isEmpty(itemList)) {
                return;
            }
            itemList.forEach(subItem -> {
                MessageInsertDTO messageInsertDTO = new MessageInsertDTO();
                messageInsertDTO.setBusinessId(item.getBusinessId())
                        .setTaskId(item.getTaskId())
                        .setTaskItemId(subItem.getTaskItemId())
                        .setMessageContent(item.getPushContent())
                        .setMessageUrl(item.getPushUrl())
                        .setMessageType(BusinessConstants.MESSAGE_TYPE_SYSTEM)
                        .setUserId(subItem.getTaskUserId())
                        .setUserName(subItem.getTaskUserName())
                        .setUserType(subItem.getTaskUserType());
                messageList.add(messageInsertDTO);
            });
        });
        messageService.addMessages(messageList);
    }

    /**
     * 处理开启任务消息推送，短信推送
     *
     * @param list    任务信息
     * @param tempMap 任务子项信息
     */
    private void startTaskPushPhone(List<BusinessTaskDO> list, Map<Integer, List<BusinessTaskItemDO>> tempMap) {
        // todo 任务信息推送 短信推送 待定
    }

    /**
     * 处理开启任务消息推送，邮件推送
     *
     * @param list    任务信息
     * @param tempMap 任务子项信息
     */
    private void startTaskPushEmail(List<BusinessTaskDO> list, Map<Integer, List<BusinessTaskItemDO>> tempMap) {
        List<EmailNormalDTO> messageList = new ArrayList<>(list.size() * 4);
        // 构建用户编号列表
        final List<Integer> userIds = new ArrayList<>(tempMap.size() * 8);
        tempMap.values().forEach(item -> {
            List<Integer> temp = item.stream()
                    .map(BusinessTaskItemDO::getTaskUserId)
                    .collect(Collectors.toList());
            userIds.addAll(temp);
        });
        if (ObjectValidators.isEmpty(userIds)) {
            return;
        }
        // 查询用户账户信息
        List<AccountDO> accountList = accountService.list(
                new LambdaQueryWrapper<AccountDO>()
                        .select(AccountDO::getAccount, AccountDO::getUserType)
                        .in(AccountDO::getAccount, userIds)
                        .eq(AccountDO::getForbidden, BusinessConstants.FORBIDDEN_NORMAL));
        // 查询用户邮箱
        if (ObjectValidators.isEmpty(accountList)) {
            return;
        }
        final List<Integer> accountIds = accountList.stream()
                .map(AccountDO::getAccount)
                .collect(Collectors.toList());
        List<UserInfoDO> userInfoList = userInfoService.list(
                new LambdaQueryWrapper<UserInfoDO>()
                        .select(UserInfoDO::getAccountId, UserInfoDO::getEmail)
                        .in(UserInfoDO::getAccountId, accountIds));
        // 转换用户信息
        Map<Integer, String> emailMap = userInfoList.stream()
                .collect(Collectors.toMap(UserInfoDO::getAccountId,
                        UserInfoDO::getEmail, (item1, item2) -> item2));
        // 构造邮件信息
        list.forEach(item -> {
            List<BusinessTaskItemDO> itemList = tempMap.get(item.getTaskId());
            if (ObjectValidators.isEmpty(itemList)) {
                return;
            }
            List<String> emailList = new ArrayList<>(itemList.size());
            itemList.forEach(subItem -> {
                String email = emailMap.get(subItem.getTaskUserId());
                if (ObjectValidators.isNotEmpty(email)) {
                    emailList.add(email);
                } else {
                    log.debug("一个为空的邮件");
                }
            });
            if (ObjectValidators.isNotEmpty(emailList)) {
                EmailNormalDTO emailNormalDTO = new EmailNormalDTO();
                emailNormalDTO.setAccounts(emailList)
                        .setTitle(item.getPushTitle())
                        .setContent(item.getPushContent());
                messageList.add(emailNormalDTO);
            } else {
                log.debug("任务邮件推送，邮件人员为空：" + item.toString());
            }
        });
        // 发送邮件
        if (ObjectValidators.isNotEmpty(messageList)) {
            feignEmailAuthCode.sendMessageList(messageList);
        } else {
            log.info("批量发送任务推送邮件取消，邮件为空。");
        }
    }

    /**
     * 处理开启任务消息推送，异步处理
     *
     * @param list     任务信息
     * @param itemList 任务子项信息
     */
    @Async
    void startTaskPushMessage(final List<BusinessTaskDO> list, final List<BusinessTaskItemDO> itemList) {
        if (ObjectValidators.isEmpty(list) || ObjectValidators.isEmpty(itemList)) {
            return;
        }
        List<BusinessTaskDO> webList = new ArrayList<>(list.size());
        List<BusinessTaskDO> phoneList = new ArrayList<>(list.size());
        List<BusinessTaskDO> emailList = new ArrayList<>(list.size());
        list.forEach(item -> {
            if (BusinessConstants.TASK_MESSAGE_PUSH_TRUE.equals(item.getPushWebFlag())) {
                webList.add(item);
            }
            if (BusinessConstants.TASK_MESSAGE_PUSH_TRUE.equals(item.getPushPhoneFlag())) {
                phoneList.add(item);
            }
            if (BusinessConstants.TASK_MESSAGE_PUSH_TRUE.equals(item.getPushEmailFlag())) {
                emailList.add(item);
            }
        });
        final Map<Integer, List<BusinessTaskItemDO>> tempMap = itemList.stream()
                .collect(Collectors.toMap(BusinessTaskItemDO::getTaskId, item -> {
                    List<BusinessTaskItemDO> tempList = new ArrayList<>();
                    tempList.add(item);
                    return tempList;
                }, (item1, item2) -> {
                    item1.addAll(item2);
                    return item1;
                }));
        if (ObjectValidators.isNotEmpty(webList)) {
            startTaskPushWeb(webList, tempMap);
        }
        if (ObjectValidators.isNotEmpty(phoneList)) {
            startTaskPushPhone(phoneList, tempMap);
        }
        if (ObjectValidators.isNotEmpty(emailList)) {
            startTaskPushEmail(emailList, tempMap);
        }
    }

    /**
     * 构造任务子项
     *
     * @param list       任务数据
     * @param insertList 插入后的任务数据
     * @return 构造好的任务子项数据
     */
    private List<BusinessTaskItemDO> createTaskItem(List<BusinessTaskStartDTO> list, List<BusinessTaskDO> insertList) {
        final String paramSplitChar = "-";

        final LocalDateTime localDateTime = LocalDateTime.now();
        AccountQueryDTO accountQueryDTO = new AccountQueryDTO();
        accountQueryDTO.setForbidden(BusinessConstants.FORBIDDEN_NORMAL);

        // 键为 taskName#businessId
        final Map<String, Integer> tempMap = insertList.stream()
                .collect(Collectors.toMap(
                        item -> item.getTaskName() + "#" + item.getBusinessId(),
                        BusinessTaskDO::getTaskId));

        // 构造任务子项
        List<BusinessTaskItemDO> itemList = new ArrayList<>(32);
        list.forEach(item -> {
            List<String> allotTypeParam = item.getAllotTypeParam();
            if (ObjectValidators.isEmpty(allotTypeParam)) {
                throw getAppException("开启任务失败！分配参数不能为空!");
            }
            Integer taskId = tempMap.get(item.getTaskName() + "#" + item.getBusinessId());
            // 快速分配
            if (BusinessConstants.ALLOT_TYPE_QUICK.equals(item.getAllotType())) {
                allotTypeParam.forEach(param -> {
                    String[] params = param.split(paramSplitChar);
                    if (ObjectValidators.isEmpty(params) || param.length() < 2) {
                        throw getAppException("开启任务失败！错误的人员参数：" + param + "  格式：id-type-name");
                    }
                    BusinessTaskItemDO businessTaskItemDO = new BusinessTaskItemDO();
                    businessTaskItemDO
                            .setTaskId(taskId)
                            .setState(BusinessConstants.TASK_STATE_NORMAL)
                            .setTaskTime(localDateTime)
                            .setTaskUserId(Integer.parseInt(params[0]))
                            .setTaskUserType(params[1])
                            .setConsumeFlag(BusinessConstants.TASK_CONSUME_FALSE)
                            .setUsable(BusinessConstants.USEABLE_TRUE);
                    if (params.length >= 3) {
                        businessTaskItemDO.setTaskUserName(params[2]);
                    }
                    itemList.add(businessTaskItemDO);
                });
            } else {
                // 全部分配
                String userType = allotTypeParam.get(0);
                if (ObjectValidators.isEmpty(userType)) {
                    throw getAppException("开启任务失败！全部分配参数不能为空！");
                }
                // 根据类型查询人员信息
                accountQueryDTO.setUserType(Collections.singletonList(userType));
                List<AccountDO> accountList = accountService.queryAccountByWrapper(accountQueryDTO);
                if (ObjectValidators.isEmpty(accountList)) {
                    throw getAppException("开启任务失败！分配人员为空!");
                }
                accountList.forEach(accountItem -> {
                    BusinessTaskItemDO businessTaskItemDO = new BusinessTaskItemDO();
                    businessTaskItemDO
                            .setTaskId(taskId)
                            .setState(BusinessConstants.TASK_STATE_NORMAL)
                            .setTaskTime(localDateTime)
                            .setTaskUserId(accountItem.getAccount())
                            .setTaskUserType(accountItem.getUserType())
                            .setTaskUserName("")
                            .setConsumeFlag(BusinessConstants.TASK_CONSUME_FALSE)
                            .setUsable(BusinessConstants.USEABLE_TRUE);
                    itemList.add(businessTaskItemDO);
                });
            }
        });
        return itemList;
    }

    /**
     * 开启任务
     *
     * @param list 开启任务参数
     * @return 开启的流程
     */
    @SuppressWarnings("AlibabaUndefineMagicConstant")
    @Override
    public List<BusinessTaskVO> startTask(List<BusinessTaskStartDTO> list) {
        if (ObjectValidators.isEmpty(list)) {
            throw getAppException("开启任务失败！参数不能为空！");
        }
        // 保存任务信息
        List<BusinessTaskDO> insertList = list.stream()
                .map(this::toBusinessTaskDO)
                .collect(Collectors.toList());

        boolean success = this.saveBatch(insertList);
        if (!success) {
            throw getAppException("开启任务失败！保存任务信息失败！");
        }

        // 构造任务子项
        List<BusinessTaskItemDO> itemList = createTaskItem(list, insertList);

        // 设置定时催办任务，在保存item之前执行
        startTaskUrge(insertList, itemList);

        success = itemService.saveBatch(itemList);
        if (!success) {
            throw getAppException("开启任务失败！保存任务子项信息失败！");
        }

        // 任务信息推送，异步调用
        startTaskPushMessage(insertList, itemList);

        List<Integer> listIds = insertList.stream()
                .map(BusinessTaskDO::getTaskId)
                .collect(Collectors.toList());
        return this.queryTaskByTaskIds(listIds);
    }

    /**
     * 提交任务
     *
     * @param list 提交任务参数
     * @return 开启的流程
     */
    @Override
    public List<BusinessTaskVO> commitTask(List<BusinessTaskCommitDTO> list) {
        if (ObjectValidators.isEmpty(list)) {
            throw getAppException("提交工作流失败！参数不能为空！");
        }
        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        LocalDateTime localDateTime = LocalDateTime.now();
        List<Integer> urgeList = new ArrayList<>(list.size());
        list.forEach(item -> {
            // 查询工作流信息
            BusinessTaskVO businessTaskVO = this.queryTaskByTaskId(item.getTaskId());
            if (ObjectValidators.isEmpty(businessTaskVO)) {
                throw getAppException("提交工作流失败，工作流不存在！");
            }
            List<BusinessTaskItemVO> itemList = businessTaskVO.getBusinessTaskItemList();
            if (ObjectValidators.isEmpty(itemList)) {
                throw getAppException("提交工作流失败，系统错误，任务子项为空!");
            }
            List<BusinessTaskItemVO> currentUserItemList = itemList.stream()
                    .filter(item2 -> cacheLoginUser.getAccount().equals(item2.getTaskUserId())
                            && cacheLoginUser.getType().equals(item2.getTaskUserType()))
                    .collect(Collectors.toList());
            if (ObjectValidators.isEmpty(currentUserItemList)) {
                throw getAppException("提交工作流失败，当前用户该任务待办事项为空!");
            }
            BusinessTaskItemVO currentUserItem = currentUserItemList.get(0);
            // 提交当前用户待办事项
            currentUserItem.setState(BusinessConstants.TASK_STATE_FINISH)
                    .setConsumeTime(localDateTime)
                    .setConsumeFlag(BusinessConstants.TASK_CONSUME_TRUE);
            boolean success = itemService.updateById(currentUserItem);
            if (!success) {
                throw getAppException("提交工作流失败！消费代办任务失败！");
            }
            // 该任务其他代办事项
            List<BusinessTaskItemDO> otherUserItemList = itemList.stream()
                    .filter(item2 -> !cacheLoginUser.getAccount().equals(item2.getTaskUserId())
                            || !cacheLoginUser.getType().equals(item2.getTaskUserType()))
                    .collect(Collectors.toList());
            // 保存当前任务的催办
            if (ObjectValidators.isNotEmpty(currentUserItem.getUrgeId())) {
                urgeList.add(currentUserItem.getUsable());
            }
            // 消费主任务标志
            boolean mainTaskConsumeFlag = false;
            // 如果是单一抢占完成，取消其他人的代办任务，消费主任务，关闭任务催办
            if (businessTaskVO.getConsumeMode().equals(BusinessConstants.TASK_CONSUME_MODE_SINGLE)) {
                if (ObjectValidators.isNotEmpty(otherUserItemList)) {
                    // 添加任务催办
                    otherUserItemList.forEach(item2 -> {
                        if (ObjectValidators.isNotEmpty(item2.getUrgeId())) {
                            urgeList.add(item2.getUrgeId());
                        }
                    });
                    // 修改数据，取消任务
                    otherUserItemList = otherUserItemList.stream()
                            .map(item2 -> item2.setState(BusinessConstants.TASK_STATE_CANCEL)
                                    .setConsumeTime(localDateTime)
                                    .setConsumeFlag(BusinessConstants.TASK_CONSUME_TRUE))
                            .collect(Collectors.toList());
                    success = itemService.updateBatchById(otherUserItemList);
                    if (!success) {
                        throw getAppException("提交工作流失败！消费其他代办任务失败！");
                    }
                }
                // 消费主任务标志
                mainTaskConsumeFlag = true;
            } else {
                // 全部完成模式，则判断是否全部子任务完成，全部子任务完成则消费主任务
                otherUserItemList = otherUserItemList.stream()
                        .filter(item2 -> !BusinessConstants.TASK_STATE_FINISH.equals(item2.getState()))
                        .collect(Collectors.toList());
                // 未完成子任务为空，消费主任务
                if (ObjectValidators.isEmpty(otherUserItemList)) {
                    mainTaskConsumeFlag = true;
                }
            }
            if (mainTaskConsumeFlag) {
                businessTaskVO.setConsumeFlag(BusinessConstants.TASK_CONSUME_TRUE)
                        .setConsumeTime(localDateTime)
                        .setConsumeUserId(cacheLoginUser.getAccount())
                        .setConsumeUserType(cacheLoginUser.getType())
                        .setConsumeUserName(cacheLoginUser.getName())
                        .setState(BusinessConstants.TASK_STATE_FINISH)
                        .setUpdateTime(localDateTime);
                success = this.updateById(businessTaskVO);
                if (!success) {
                    throw getAppException("提交工作流失败！消费工作流失败！");
                }
            }
        });

        // 关闭任务催办
        if (ObjectValidators.isNotEmpty(urgeList)) {
            closeUrge(urgeList);
        }

        return null;
    }

    /**
     * 关闭任务
     *
     * @param list 关闭流程参数
     * @return 是否关闭成功
     */
    @Override
    public Boolean closeTask(List<BusinessTaskCloseDTO> list) {
        if (ObjectValidators.isEmpty(list)) {
            throw getAppException("关闭任务失败！参数不能为空！");
        }

        CacheLoginUser cacheLoginUser = currentLoginUserCacheNotNull();
        LocalDateTime localDateTime = LocalDateTime.now();

        // 关闭推送任务
        List<Integer> urgeList = null;
        List<Integer> taskIds = list.stream()
                .map(BusinessTaskCloseDTO::getTaskId)
                .collect(Collectors.toList());
        if (ObjectValidators.isNotEmpty(taskIds)) {
            List<BusinessTaskVO> taskList = this.queryTaskByTaskIds(taskIds);
            urgeList = taskList.stream()
                    .filter(item -> BusinessConstants.TASK_URGE_FLAG_TRUE.equals(item.getUrgeFlag()))
                    .flatMap(item -> ObjectValidators.isEmpty(item.getBusinessTaskItemList())
                            ? Stream.empty() : item.getBusinessTaskItemList().stream())
                    .map(BusinessTaskItemVO::getUrgeId)
                    .filter(item -> ObjectValidators.isNotEmpty(item) && item > 0)
                    .collect(Collectors.toList());
        }

        list.forEach(item -> {
            // 更新主任务信息
            BusinessTaskDO updateDO = new BusinessTaskDO();
            updateDO.setState(BusinessConstants.TASK_STATE_CANCEL)
                    .setUpdateUserId(cacheLoginUser.getAccount())
                    .setUpdateUserName(cacheLoginUser.getName())
                    .setUpdateUserType(cacheLoginUser.getType())
                    .setUpdateTime(localDateTime)
                    .setConsumeFlag(BusinessConstants.TASK_CONSUME_TRUE)
                    .setConsumeUserId(cacheLoginUser.getAccount())
                    .setConsumeUserName(cacheLoginUser.getName())
                    .setConsumeUserType(cacheLoginUser.getType())
                    .setConsumeTime(localDateTime)
                    .setState(BusinessConstants.TASK_STATE_CANCEL)
                    .setRemark(item.getRemark());
            this.update(updateDO, new LambdaUpdateWrapper<BusinessTaskDO>()
                    .eq(BusinessTaskDO::getTaskId, item.getTaskId())
                    .eq(BusinessTaskDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE)
                    .eq(BusinessTaskDO::getState, BusinessConstants.TASK_STATE_NORMAL));

            // 更新任务子项
            BusinessTaskItemDO businessTaskItemDO = new BusinessTaskItemDO();
            businessTaskItemDO.setConsumeFlag(BusinessConstants.MESSAGE_CONSUME_TRUE)
                    .setConsumeTime(localDateTime)
                    .setState(BusinessConstants.TASK_STATE_CANCEL)
                    .setRemark(item.getRemark());
            itemService.update(businessTaskItemDO, new LambdaUpdateWrapper<BusinessTaskItemDO>()
                    .eq(BusinessTaskItemDO::getTaskId, item.getTaskId())
                    .eq(BusinessTaskItemDO::getConsumeFlag, BusinessConstants.TASK_CONSUME_FALSE)
                    .eq(BusinessTaskItemDO::getState, BusinessConstants.TASK_STATE_NORMAL));
        });

        // 关闭定时催办
        if (ObjectValidators.isNotEmpty(urgeList)) {
            closeUrge(urgeList);
        }
        return true;
    }

    /**
     * 关闭任务催办
     *
     * @param list 催办ID列表
     */
    @Async
    void closeUrge(List<Integer> list) {
        if (ObjectValidators.isEmpty(list)) {
            return;
        }
        // todo 关闭任务催办
    }
}
